import assert from "assert";
import it from "./it.js";
import jsdom from "./jsdom.js";
import deepEqualData from "./deepEqualData.js";
import * as d3 from "d3-selection";
import * as d3_graphviz from "../index.js";
import {translatePointsAttribute} from "../src/svg.js";
import SharedWorker from "./polyfill_SharedWorker.js";

describe("drawNode()", () => {
    let actualGraphviz;
    let expectedGraphviz;

    afterEach(() => {
        expectedGraphviz._worker.port.close();
        actualGraphviz._worker.port.close();
        global.SharedWorker = undefined;
    });

    it("Verify that polygon shape is drawn exactly as Graphviz does.", async () => {
        var window = global.window = jsdom(
            `
                <script src="http://dummyhost/test/@hpcc-js/wasm/dist/wrapper.js" type="javascript/worker"></script>
                <div id="expected-graph"></div><div id="actual-graph"></div>
                `,
        );
        global.document = window.document;
        global.Blob = function (jsarray) {
            return new Function(jsarray[0]);
        }
        window.URL.createObjectURL = function (js) {
            return js;
        }
        global.SharedWorker = SharedWorker;
        var expectedGraph = d3.select("#expected-graph");
        var actualGraph = d3.select("#actual-graph");

        await new Promise(resolve => {
            expectedGraphviz = d3_graphviz.graphviz("#expected-graph", { useSharedWorker: true })
                .on('initEnd', resolve);
        });

        await new Promise(resolve => {
            actualGraphviz = d3_graphviz.graphviz("#actual-graph", { useSharedWorker: true })
                .on('initEnd', resolve);
        });

        await new Promise(resolve => {
            expectedGraphviz
                .zoom(false)
                .renderDot('digraph {a [shape="polygon"]}', resolve);
        });

        await new Promise(resolve => {
            actualGraphviz
                .renderDot('digraph {}', resolve);
        });

        var x = 27;
        var y = -18;
        actualGraphviz
            .drawNode(x, y, 'a', { shape: 'polygon', id: 'node1' })
            .insertDrawnNode('a');

        const expectedNodeGroup = expectedGraph.selectAll('.node');
        const expectedNodeTitle = expectedNodeGroup.selectAll('title');
        const expectedNodeShape = expectedNodeGroup.selectAll('polygon');
        const expectedNodeText = expectedNodeGroup.selectAll('text');

        const actualNodeGroup = actualGraph.selectAll('.node');
        const actualNodeTitle = actualNodeGroup.selectAll('title');
        const actualNodeShape = actualNodeGroup.selectAll('polygon');
        const actualNodeText = actualNodeGroup.selectAll('text');

        var bbox = expectedNodeShape.node().getBBox();
        bbox.cx = bbox.x + bbox.width / 2;
        bbox.cy = bbox.y + bbox.height / 2;
        var xoffs = x - bbox.cx;
        var yoffs = y - bbox.cy;

        assert.equal(actualNodeGroup.attr("id"), expectedNodeGroup.attr("id"), 'id of group');

        assert.equal(actualNodeTitle.text(), expectedNodeTitle.text(), 'text of title');

        assert.equal(actualNodeShape.attr("fill"), expectedNodeShape.attr("fill"), 'fill of polygon');
        assert.equal(actualNodeShape.attr("stroke"), expectedNodeShape.attr("stroke"), 'stroke of polygon');
        assert.equal(actualNodeShape.attr("points"), translatePointsAttribute(expectedNodeShape.attr("points"), xoffs, yoffs), 'points of polygon');

        assert.equal(actualNodeText.attr("text-anchor"), expectedNodeText.attr("text-anchor"), 'text-anchor of text');
        assert.equal(+actualNodeText.attr("x"), +expectedNodeText.attr("x") + xoffs, 'x of text');
        assert.equal(+actualNodeText.attr("y"), +expectedNodeText.attr("y") + yoffs, 'y of text');
        assert.equal(actualNodeText.attr("font-family"), expectedNodeText.attr("font-family"), 'font-family of text');
        assert.equal(actualNodeText.attr("font-size"), expectedNodeText.attr("font-size"), 'font-size of text');
        assert.equal(actualNodeText.attr("fill"), expectedNodeText.attr("fill"), 'fill of text');

        assert.equal(actualNodeText.text(), expectedNodeText.text(), 'text of node group');

        var actualNodeGroupDatum = actualNodeGroup.datum();
        var expectedNodeGroupDatum = expectedNodeGroup.datum();
        delete expectedNodeGroupDatum.parent;
        deepEqualData(actualNodeGroupDatum, expectedNodeGroupDatum, 'data of drawn node of shape equals Graphviz generated data');

    });
});
